"use strict";

var _class, _descriptor;
function _initializerDefineProperty(target, property, descriptor, context) { if (!descriptor) return; Object.defineProperty(target, property, { enumerable: descriptor.enumerable, configurable: descriptor.configurable, writable: descriptor.writable, value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); }
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object.keys(descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object.defineProperty(target, property, desc); desc = null; } return desc; }
function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'transform-class-properties is enabled and runs after the decorators transform.'); }
function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get.bind(); } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }
function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct.bind(); } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
function _isNativeFunction(fn) { try { return Function.toString.call(fn).indexOf("[native code]") !== -1; } catch (e) { return typeof fn === "function"; } }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
// es5 构造函数 模拟类 函数的名字大写

function AnimalFn() {
  this.type = '哺乳类';
  this.a = {};
}
AnimalFn.prototype.home = {};
AnimalFn.prototype.fn = function () {};
// 类一类事物  具体的一个实例
// 私有属性 是外面拿不到的  
// 1.实例上的属性
// 2.公共属性
// 3.静态方法 静态属性 只能通过类来调用
var animal1 = new AnimalFn(); // new 实现原理
var animal2 = new AnimalFn(); // new 实现原理
console.log(animal1);

// 每个对象上都会有一个__proto__ 找所属类的原型 .__proto__ = X.prototype
console.log(animal1.__proto__ == AnimalFn.prototype); //true
console.log(AnimalFn.prototype.__proto__ == Object.prototype); //true
console.log(Object.prototype.__proto__); //null

console.log(Object.__proto__ == Function.prototype); //true
console.log(Function.__proto__ == Function.prototype); //true
console.log(Object.__proto__ === Function.__proto__); //true

// constructor
console.log(AnimalFn.prototype.constructor === AnimalFn); //true
console.log(animal1.constructor); // 获取的是类 无法拿到类实例的属性 可以拿到静态属性或者方法

// 继承
// 实例的属性 公共属性
//一般使用：call + Object.create 或 call + setPrototypeOf

function Animal(name) {
  this.type = '哺乳类';
  this.name = name;
}
Animal.prototype.eat = function () {
  console.log('吃饭');
};
function Tiger(name) {
  // Animal.call(name);
  Animal.call(this);
}
// 1)老虎增加方法 可以增加到自己的身上 还可以找到Animal原型
//Tiger.prototype = Animal.prototype //错误的
Tiger.prototype.__proto__ = Animal.prototype; //等价下面的方法
Object.setPrototypeOf(Tiger.prototype, Animal.prototype); //es6
var tiger = new Tiger();
console.log(tiger.type);
console.log(tiger.eat());

// 2)Object.create()  es5
function create(Pproto) {
  var Fn = function Fn() {};
  Fn.prototype = Pproto; // 把父类的原型 放到Fn上
  return new Fn();
}
// 让tiger的原型 执行 Fn函数的实例
// 找的时候 想找自己身上 找不到找对应的链 链放的是fn的实例，fn找不到 会找到父类的原型
Tiger.prototype = Object.create(Animal.prototype, {
  constructor: {
    value: Tiger
  }
});
var tiger1 = new Tiger();
console.log(tiger1.constructor);

// 3) 用不到 不能给父类传递参数
Tiger.prototype = new Animal(); // {动物的实例属性 公共属性}
var tiger2 = new Tiger('xxx');
console.log(tiger2.name);

//es6
//30
var Animal1 = /*#__PURE__*/function () {
  //实例
  function Animal1(name) {
    _classCallCheck(this, Animal1);
    this.name = name;
    this.eat = '吃肉';
  }
  //公有
  _createClass(Animal1, [{
    key: "gougou",
    value: function gougou() {
      return 'dididada';
    }
  }, {
    key: "jiji",
    value: function jiji(temp) {
      if (!isNaN(temp)) {
        return Number(temp) + 20;
      } else {
        return 'Hello |' + this.eat + '| ' + temp;
      }
    }
  }], [{
    key: "flag",
    value:
    //静态
    //static flag = 'abc';es7语法，node不支持
    function flag() {
      return 123;
    }
  }]);
  return Animal1;
}();
var p = new Animal1();
console.log(p);
console.log(p.jiji(50));
console.log(p.jiji('bobo'));
console.log(p.gougou());

//继承
var Tiger5 = /*#__PURE__*/function (_Animal) {
  _inherits(Tiger5, _Animal);
  var _super = _createSuper(Tiger5);
  function Tiger5() {
    _classCallCheck(this, Tiger5);
    return _super.apply(this, arguments);
  }
  return _createClass(Tiger5);
}(Animal1);
var tiger3 = new Tiger5();
console.log(tiger3.eat);
console.log(tiger3.gougou);
var tiger4 = new Tiger5('大老虎');
console.log(tiger4.name);
console.log(Tiger5.flag(), '静态方法可以被继承，只能通过类来调用');
var Tiger6 = /*#__PURE__*/function (_Animal2) {
  _inherits(Tiger6, _Animal2);
  var _super2 = _createSuper(Tiger6);
  function Tiger6(name) {
    _classCallCheck(this, Tiger6);
    return _super2.call(this, name);
  }
  return _createClass(Tiger6);
}(Animal1);
var tiger7 = new Tiger6('小老虎');
console.log(tiger7.name);
var Ary = /*#__PURE__*/function (_Array) {
  _inherits(Ary, _Array);
  var _super3 = _createSuper(Ary);
  function Ary() {
    var _this;
    _classCallCheck(this, Ary);
    _this = _super3.call(this); //必须要加才能用this
    _this.a = '10';
    _this.b = '20';
    return _this;
  }
  _createClass(Ary, [{
    key: "fn",
    value: function fn(arg) {
      if (this.length > 4) {
        //使用super调用继承的数组方法排序，只要length>4就不会再添加项而是去排序
        _get(_getPrototypeOf(Ary.prototype), "sort", this).call(this, function (a, b) {
          return a - b;
        });
      } else {
        if (arg < 1) {
          return this.push(this.a);
        } else if (arg == 1) {
          return this.push(1);
        } else {
          return this.push(this.b);
        }
      }
    }
  }]);
  return Ary;
}( /*#__PURE__*/_wrapNativeSuper(Array));
var aa = new Ary();
var SuperArray = /*#__PURE__*/function (_Array2) {
  _inherits(SuperArray, _Array2);
  var _super4 = _createSuper(SuperArray);
  function SuperArray() {
    _classCallCheck(this, SuperArray);
    return _super4.apply(this, arguments);
  }
  _createClass(SuperArray, [{
    key: "shuffle",
    value: function shuffle() {
      for (var i = this.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        //数组解构赋值，先拿到所有的值，再去找对应的项赋值
        var _ref = [this[j], this[i]];
        this[i] = _ref[0];
        this[j] = _ref[1];
      }
    }
  }]);
  return SuperArray;
}( /*#__PURE__*/_wrapNativeSuper(Array));
var a = new SuperArray(1, 2, 3, 4, 5);
console.log(a);
a.shuffle();
console.log(a);

//浏览器不支持，需要babel转译es5才能运行
//装饰器 可以修饰类，类的属性，类的原型上的方法
//修饰的时候把这个类 属性... 传递给修饰的函数
// @flag
var Animal3 = (_class = /*#__PURE__*/function () {
  function Animal3() {
    _classCallCheck(this, Animal3);
    _initializerDefineProperty(this, "PI", _descriptor, this);
    this.name = 'xxx';
  }
  _createClass(Animal3, [{
    key: "say",
    value: function say(a, b, c) {
      console.log('说话', a, b, c);
    }
  }]);
  return Animal3;
}(), (_descriptor = _applyDecoratedDescriptor(_class.prototype, "PI", [readonly], {
  configurable: true,
  enumerable: true,
  writable: true,
  initializer: function initializer() {
    return 3.14;
  }
}), _applyDecoratedDescriptor(_class.prototype, "say", [before], Object.getOwnPropertyDescriptor(_class.prototype, "say"), _class.prototype)), _class); //类的静态属性
// function flag(constructor) {
//   constructor.type = '哺乳类'
// }
// console.log(Animal.type)
//类的属性（实例上的属性）
//target==Animal.prototype
function readonly(target, property, descriptor) {
  descriptor.writable = false;
}
var animal3 = new Animal3();
//animal3.PI = 3.15 //报错，装饰器设置了不可更改
function before(target, property, descriptor) {
  var oldSay = descriptor.value;
  descriptor.value = function () {
    console.log('before');
    oldSay.call.apply(oldSay, [target].concat(Array.prototype.slice.call(arguments)));
  };
}
animal3.say(1, 2, 3);
